package controllers;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import models.Assignment;
import models.CheatingCase;
import models.Submission;
import notifiers.Mails;
import others.DumbFS;
import others._;
import play.mvc.Controller;
import play.mvc.With;
import textdiff.Report;
import textdiff.TextDiff;

@With (Secure.class)
public class Submissions extends Controller {

	@Check ("ta")
	public static void pick(long subId) {
		Submission sub = Submission.findById(subId);
		List<Submission> ss = Submission.find("byAssignmentAndStudent", sub.assignment, sub.student).fetch();
		for (Submission s : ss) {
			s.toGrade = false;
			s.save();
		}
		sub.toGrade = true;
		sub.save();
		Show.assignmentSubmissions(sub.assignment.id);
	}
	@Check ("ta")
	public static void processCase(long caseId, int action, String comment, String cc) {
		CheatingCase c = CheatingCase.findById(caseId);
		if (comment.length() < 5) {
			comment = null;
		}
		notFoundIfNull(c);
		notFoundIfNull(comment);
		c.verified = true;
		String message = "Dear " + c.s1.student.username + ", " + c.s2.student.username + ",<br /><br />Your cheating case has been reviewed and ";
		switch (action) {
			case 0:
				message += "<b>neither</b> of you has been blamed.";
				break;
			case 1:
				message += "<b>" + c.s1.student.username + "</b> has been blamed.";
				c.blame1 = true;
				break;

			case 2:
				message += "<b>" + c.s2.student.username + "</b> has been blamed.";
				c.blame2 = true;
				break;

			case 3:
				message += "you <b>have both been blamed</b>.";
				c.blame1 = c.blame2 = true;
				break;
		}
		message += " The comment by the instructor that reviewed your case was: " + comment;
		c.comment = message;
		c.save();
		Mails.blame(c, message, cc);
	}

	@Check ("ta")
	public static void viewCandidates() {
		List<CheatingCase> cases = CheatingCase.find("verified=? order by percentage desc", false).fetch();
		render(cases);
	}

	public static void submitNew(long assignmentId, File file) throws IOException {
		if (file == null || file.length() > _.maxSubmissionSize) {
			flash.error("File does not exist or larger than " + _.maxSubmissionSize + " bytes");
			Show.assignment(assignmentId);
		}

		Assignment assignment = Assignment.findById(assignmentId);
		boolean pick = assignment.deadline >= new Date().getTime();
		if (pick) {
			List<Submission> subs = Submission.find("byAssignment.idAndStudent", assignmentId, Security.getStudent()).fetch();
			for (Submission sub : subs) {
				sub.toGrade = false;
				sub.save();
			}
		}
		Submission sub = new Submission();
		sub.assignment = assignment;
		sub.student = Security.getStudent();
		sub.toGrade = pick;
		sub.save();

		DumbFS.getInstance().saveSubmission(sub, file);
		if (pick) {
			flash.success("Submission made successfully. Your last submission was marked as your picked submission, change that for your convenience.");
		} else {
			flash.error("Submission made successfully. The submission you made is after the deadline and cannot be picked for grading unless by a TA.");
		}
		Show.assignment(assignmentId);
	}

	@Check ("ta")
	public static void compareSubmissions(String s1, String s2) throws Exception {
		String[] tmp = s1.split("[.]");
		long s1Id = Long.parseLong(tmp[0]);
		s1 = s1.substring(tmp[0].length() + 1);

		tmp = s2.split("[.]");
		long s2Id = Long.parseLong(tmp[0]);
		s2 = s2.substring(tmp[0].length() + 1);

		Submission ss1 = Submission.findById(s1Id);
		Submission ss2 = Submission.findById(s2Id);

		ZipFile submissionFiles;
		Enumeration entries;

		String[] file1 = null, file2 = null;

		submissionFiles = new ZipFile(DumbFS.getInstance().getSubmission(ss1));
		entries = submissionFiles.entries();
		while (entries.hasMoreElements()) {
			ZipEntry entry = (ZipEntry) entries.nextElement();
			if (entry.isDirectory())
				continue;
			if (!Application.hash(entry.getName()).equals(s1))
				continue;
			StringBuffer buffer = new StringBuffer();
			BufferedReader br = new BufferedReader(new InputStreamReader(submissionFiles.getInputStream(entry)));
			while (true) {
				String line = br.readLine();
				if (line == null)
					break;
				buffer.append(line);
				buffer.append("\n");
			}

			file1 = buffer.toString().split("\n");
			break;
		}

		submissionFiles = new ZipFile(DumbFS.getInstance().getSubmission(ss2));
		entries = submissionFiles.entries();
		while (entries.hasMoreElements()) {
			ZipEntry entry = (ZipEntry) entries.nextElement();
			if (entry.isDirectory())
				continue;
			if (!Application.hash(entry.getName()).equals(s2))
				continue;
			StringBuffer buffer = new StringBuffer();
			BufferedReader br = new BufferedReader(new InputStreamReader(submissionFiles.getInputStream(entry)));
			while (true) {
				String line = br.readLine();
				if (line == null)
					break;
				buffer.append(line);
				buffer.append("\n");
			}

			file2 = buffer.toString().split("\n");
			break;
		}

		Report report = new TextDiff().compare(file1, file2);
		renderText(report);
	}
}
